home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Graphics 2D / New NewGWorld / New NewGWorld.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-28  |  19.8 KB  |  684 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        New NewGWorld.c
  3.  
  4.     Contains:    Sample application demonstrating the use of the new version of the NewGWorld routine
  5.  
  6.     Written by:    ggs
  7.  
  8.     Copyright:    Copyright (c) 1999 Apple Computer, Inc., All Rights Reserved.
  9.  
  10.                 You may incorporate this Apple sample source code into your program(s) without
  11.                 restriction. This Apple sample source code has been provided "AS IS" and the
  12.                 responsibility for its operation is yours. You are not permitted to redistribute
  13.                 this Apple sample source code as "Apple sample source code" after having made
  14.                 changes. If you're going to re-distribute the source, we require that you make
  15.                 it clear in the source that the code was descended from Apple sample source
  16.                 code, but that you've made changes.
  17.                 
  18.     Change History (most recent first):
  19.                 08/2000        JM                Carbonized, non-Carbon code is commented out
  20.                                             for demonstration purposes.
  21.  
  22. */
  23.  
  24. #include "CarbonPrefix.h"
  25. // system includes ----------------------------------------------------------
  26.  
  27. #include <MacMemory.h>
  28. #include <Events.h>
  29. #include <Fonts.h>
  30. #include <Windows.h>
  31. #include <TextEdit.h>
  32. #include <Dialogs.h>
  33. #include <Devices.h>
  34. #include <Sound.h>
  35. #include <SoundInput.h>
  36. #include <ToolUtils.h>
  37. #include <OSUtils.h>
  38. #include <LowMem.h>
  39. #include <Gestalt.h>
  40.  
  41. #include <stdlib.h>
  42.  
  43. // project includes ---------------------------------------------------------
  44.  
  45.  
  46.  
  47. // statics/globals (internal only) ------------------------------------------
  48.  
  49. // Menu defs
  50. enum 
  51. {
  52.     kMenuApple = 128,
  53.     kMenuFile = 129,
  54.     
  55.     kAppleAbout = 1,    
  56.     kFileInVRAM = 1,                        // allocate buffer in VRAM
  57.     kFileInAGP,                                // allocate buffer in AGP memory
  58.     kFileInSystem,                            // allocate buffer in system memory
  59.     kFileTest,                                // run blitting test
  60.     kFileQuit                                // quit
  61. };
  62.  
  63. enum
  64. {
  65.                                             // Initial Window Constants
  66.     kWindowHeight = 400,                    //   "
  67.     kWindowWidth = 500,                        //   "
  68.     kWindowOffset = 100                        //   "
  69. };
  70.  
  71. enum
  72. {
  73.     kNoWhere = 0,                            // where is the off screen
  74.     kInVRAM,
  75.     kInAGP,
  76.     kInSystem
  77. };
  78.  
  79. Boolean gDone = false;                        // is app done
  80. SInt32 gSleepTime = 60;                        // yield time
  81.  
  82. WindowPtr gpWindow = NULL;                    // main window
  83. GWorldPtr gpGWOffScreen = NULL;                // main window offscreen scratch
  84. short gwLocOffscreen = 0;                    // curretn offscreen location
  85.  
  86. Boolean gNewNewGWorld = false;                // can we allocate in VRAm or AGP memory?
  87.  
  88.  
  89. // functions Prototypes (internal/private) -----------------------------------
  90.  
  91. // returns GDHandle that window resides on (most of it anyway)
  92. GDHandle GetWindowDevice (WindowPtr pWindow);
  93. // checks and allocates (if required) a new GWorld size of pWindow in memory type target; returns true if (re)allocated
  94. Boolean BuildOffscreen (GWorldPtr * ppGWorld, WindowPtr pWindow, short * target);
  95. // fills offscreen buffer with random bright color
  96. void FillOffscreen (GWorldPtr pGWorld);
  97. // checks offscreen and blits it to the front
  98. void BlitToWindow (GWorldPtr pGWorld, WindowPtr pWindow, short * pLocation);
  99. // checks buffer and then runs 200 iteration CopyBits test offscreen to on and reprots results
  100. void RunTest (void);
  101. // Forces offscreen allocation (if different than current) in memory type specified and sets menu flag
  102. void AllocBuffer (short target);
  103.  
  104. // standard stuff
  105. void InitToolbox(void);                                                    // standard inits
  106. Boolean SetUp (void);                                                    // application setup
  107. void DoMenu (SInt32 menuResult);                                        // menu event handler
  108. void DoKey (SInt8 theKey, SInt8 theCode);                                // key down handling
  109. void DoUpdate (WindowPtr pWindow);                                        // draw from off screen to on and updates control postions on screen for events
  110. void DoEvent (void);                                                    // event handler
  111. void CleanUp (void);                                                    // clean ups after application
  112.  
  113. // functions (internal/private) ---------------------------------------------
  114.  
  115. // returns GDHandle that window resides on (most of it anyway)
  116.  
  117. GDHandle GetWindowDevice (WindowPtr pWindow)
  118. {
  119.     GrafPtr pgpSave;
  120.     Rect rectWind, rectSect;
  121.     long greatestArea, sectArea;
  122.     GDHandle hgdNthDevice, hgdZoomOnThisDevice;
  123.     
  124.     GetPort (&pgpSave);
  125.     //SetPort (pWindow);
  126.     SetPortWindowPort (pWindow);
  127.     //rectWind = pWindow->portRect;
  128.     GetPortBounds(GetWindowPort(pWindow), &rectWind);
  129.     LocalToGlobal ((Point*)& rectWind.top);    // convert to global coordinates
  130.     LocalToGlobal ((Point*)& rectWind.bottom);
  131.     hgdNthDevice = GetDeviceList ();
  132.     greatestArea = 0;     // initialize to 0
  133.     // check window against all gdRects in gDevice list and remember 
  134.     //  which gdRect contains largest area of window}
  135.     while (hgdNthDevice)
  136.     {
  137.         if (TestDeviceAttribute (hgdNthDevice, screenDevice))
  138.             if (TestDeviceAttribute (hgdNthDevice, screenActive))
  139.             {
  140.                 // The SectRect routine calculates the intersection 
  141.                 //  of the window rectangle and this gDevice 
  142.                 //  rectangle and returns TRUE if the rectangles intersect, 
  143.                 //  FALSE if they don't.
  144.                 SectRect(&rectWind, &(**hgdNthDevice).gdRect, &rectSect);
  145.                 // determine which screen holds greatest window area
  146.                 //  first, calculate area of rectangle on current device
  147.                 sectArea = (long)(rectSect.right - rectSect.left) * (rectSect.bottom - rectSect.top);
  148.                 if ( sectArea > greatestArea )
  149.                 {
  150.                     greatestArea = sectArea;    // set greatest area so far
  151.                     hgdZoomOnThisDevice = hgdNthDevice;    // set zoom device
  152.                 }
  153.                 hgdNthDevice = GetNextDevice(hgdNthDevice);
  154.             }
  155.     }     // of WHILE
  156.     SetPort (pgpSave);
  157.     return hgdZoomOnThisDevice;
  158. }
  159.  
  160. // --------------------------------------------------------------------------
  161.  
  162. // checks and allocates (if required) a new GWorld size of pWindow in memory type target; returns true if (re)allocated
  163. // Currently, this routine checks to see if the GWorld is NULL, the PixMap is NULL, the baseAddr is NULL, the GDevice of the PixMap
  164. //   and the window do not match, and if the color depths are not the same.  If any of the previous is true the GWorld is re-allocated.
  165.  
  166. Boolean BuildOffscreen (GWorldPtr * ppGWorld, WindowPtr pWindow, short * location)
  167.     GDHandle hgdWindow = GetWindowDevice (pWindow);    // window GDevice
  168.     //short wPixDepth = (**((CGrafPtr)pWindow)->portPixMap).pixelSize; // window pixel depth
  169.     short wPixDepth = (**(GetPortPixMap(GetWindowPort(pWindow)))).pixelSize;
  170.     Boolean fMustRebuild = false;
  171.     Rect    tempRect1;
  172.     
  173.     if (NULL == *ppGWorld) // if GWorld passed in is not allocated
  174.         fMustRebuild = true;
  175.     else
  176.     {
  177.         PixMapHandle hPixmap = GetGWorldPixMap (*ppGWorld);
  178.         if ((NULL == hPixmap) || (NULL == GetPixBaseAddr (hPixmap))) // if pixmap handle is NULL or pixmap base address is NULL
  179.             fMustRebuild = true;
  180.         else if (GetGWorldDevice(*ppGWorld) != hgdWindow) // if GWorld not on same device as window
  181.             fMustRebuild = true;
  182.         else if ((**hPixmap).pixelSize != wPixDepth) // if color depths are not the same
  183.             fMustRebuild = true;
  184.     }
  185.     
  186.     if (fMustRebuild) // must rebuild
  187.     {    
  188.         if (NULL != *ppGWorld) // if we have an allocated GWorld
  189.         {
  190.             DisposeGWorld (*ppGWorld);    // dump our current GWorld
  191.             *ppGWorld = NULL;
  192.         }
  193.         switch (*location) // where to we want to put it
  194.         {
  195.             case kInVRAM:
  196.                 //if (noErr == NewGWorld (ppGWorld, wPixDepth, &pWindow->portRect, NULL, hgdWindow, noNewDevice | useDistantHdwrMem))                
  197.                 if (noErr == NewGWorld (ppGWorld, wPixDepth, GetPortBounds(GetWindowPort(pWindow), &tempRect1), NULL, hgdWindow, noNewDevice | useDistantHdwrMem))        
  198.                     break;
  199.                 // we failed with VRAM, signal that and drop to AGP
  200.                 SysBeep (30);
  201.                 *location = kInAGP;
  202.             case kInAGP:
  203.                 //if (noErr == NewGWorld (ppGWorld, wPixDepth, &pWindow->portRect, NULL, hgdWindow, noNewDevice | useLocalHdwrMem))
  204.                 if (noErr == NewGWorld (ppGWorld, wPixDepth, GetPortBounds(GetWindowPort(pWindow), &tempRect1), NULL, hgdWindow, noNewDevice | useLocalHdwrMem))
  205.                     break;
  206.                 // we failed with AGP, signal that and drop to system memory
  207.                 SysBeep (30);
  208.                 *location = kInSystem;
  209.             case kInSystem:
  210.             default:
  211.                 //if (noErr != NewGWorld (ppGWorld, wPixDepth, &pWindow->portRect, NULL, hgdWindow, noNewDevice | keepLocal))
  212.                 if (noErr != NewGWorld (ppGWorld, wPixDepth, GetPortBounds(GetWindowPort(pWindow), &tempRect1), NULL, hgdWindow, noNewDevice | keepLocal))
  213.                 {
  214.                     // we failed with system thus we can't allocate our GWorld, signal that, indicate no location and drop to debugger
  215.                     SysBeep (30);
  216.                     *location = kNoWhere;
  217.                     DebugStr ("\pUnable to allocate off screen image");
  218.                     return false; // nothing was allocated
  219.                 }
  220.         } 
  221.         return true; // we rebuilt our GWorld
  222.     }
  223.     return false; // everything is okay
  224. }
  225.  
  226. // --------------------------------------------------------------------------
  227.  
  228. // fills offscreen buffer with random bright color
  229.  
  230. void FillOffscreen (GWorldPtr pGWorld)
  231. {
  232.     static RGBColor rgbColorOld;
  233.     GDHandle hGDSave;
  234.     CGrafPtr pCGrafSave;
  235.     Rect rectSource /*= (pGWorld->portRect)*/;
  236.     RGBColor rgbColor;
  237.     
  238.     GetPortBounds(pGWorld, &rectSource);
  239.     
  240.     do 
  241.         rgbColor.red = (Random () + 32767) / 2 + 32767;
  242.     while (abs (rgbColor.red - rgbColorOld.red) <  3000);    
  243.     do 
  244.         rgbColor.green = (Random () + 32767) / 2 + 32767;
  245.     while (abs (rgbColor.green - rgbColorOld.green) <  3000);
  246.     do 
  247.         rgbColor.blue = (Random () + 32767) / 2 + 32767;
  248.     while (abs (rgbColor.blue - rgbColorOld.blue) <  3000);
  249.     
  250.     rgbColorOld = rgbColor;
  251.  
  252.     GetGWorld (&pCGrafSave, &hGDSave);
  253.     SetGWorld (pGWorld, NULL);
  254.     if (LockPixels (GetGWorldPixMap (pGWorld)))
  255.     {
  256.         // draw some background
  257.         EraseRect (&rectSource);
  258.         RGBForeColor (&rgbColor);
  259.         PaintRect (&rectSource);
  260.         UnlockPixels (GetGWorldPixMap (pGWorld));
  261.     }
  262.     SetGWorld (pCGrafSave, hGDSave);
  263. }
  264.  
  265. // --------------------------------------------------------------------------
  266.  
  267. // checks offscreen and blits it to the front
  268.  
  269. void BlitToWindow (GWorldPtr pGWorld, WindowPtr pWindow, short * pLocation)
  270. {
  271.     Rect rectDest /*= ((GrafPtr)pWindow)->portRect*/;
  272.     Rect rectSource /*= ((GrafPtr)pWindow)->portRect*/;
  273.     GrafPtr pCGrafSave;
  274.     
  275.     GetPortBounds(GetWindowPort(pWindow), &rectDest);
  276.     GetPortBounds(GetWindowPort(pWindow), &rectSource);
  277.     
  278.     // check to ensure we have a valid offscreen and rebuild if required
  279.     if (BuildOffscreen (&pGWorld, pWindow, pLocation))
  280.         FillOffscreen (pGWorld);
  281.     
  282.     // blit
  283.     GetPort (&pCGrafSave);
  284.     //SetPort ((GrafPtr) pWindow);
  285.     SetPortWindowPort(pWindow);
  286.     if (LockPixels (GetGWorldPixMap (pGWorld)))
  287.     {
  288.         //CopyBits (&((GrafPtr)pGWorld)->portBits, &pWindow->portBits, &rectSource, &rectDest, srcCopy, NULL);
  289.         CopyBits (    GetPortBitMapForCopyBits(pGWorld), GetPortBitMapForCopyBits(GetWindowPort(pWindow)), 
  290.                     &rectSource, &rectDest, srcCopy, NULL);
  291.         UnlockPixels (GetGWorldPixMap (pGWorld));
  292.     }
  293.     else
  294.         SysBeep (30);
  295.     SetPort (pCGrafSave);
  296. }
  297.  
  298. // --------------------------------------------------------------------------
  299.  
  300. // checks buffer and then runs 200 iteration CopyBits test offscreen to on and reprots results
  301.  
  302. void RunTest (void)
  303. {
  304.     Str255 str = "\p";
  305.     Rect rectDest /*= ((GrafPtr)gpWindow)->portRect*/;
  306.     Rect rectSource /*= ((GrafPtr)gpWindow)->portRect*/;
  307.     GrafPtr pCGrafSave;
  308.     long time;
  309.     short i;
  310.     
  311.     GetPortBounds(GetWindowPort(gpWindow), &rectDest);
  312.     GetPortBounds(GetWindowPort(gpWindow), &rectSource);
  313.  
  314.     BlitToWindow (gpGWOffScreen, gpWindow, &gwLocOffscreen);
  315.  
  316.     GetPort (&pCGrafSave);
  317.     //SetPort ((GrafPtr) gpWindow); //shouldn't this blow up in carbon?
  318.     SetPortWindowPort(gpWindow);
  319.     if (LockPixels (GetGWorldPixMap (gpGWOffScreen)))
  320.     {
  321.         time = TickCount ();
  322.         for (i = 0; i < 200; i++)
  323.             //CopyBits (&((GrafPtr)gpGWOffScreen)->portBits, &gpWindow->portBits, &rectSource, &rectDest, srcCopy, NULL);
  324.             CopyBits (GetPortBitMapForCopyBits(gpGWOffScreen), GetPortBitMapForCopyBits(GetWindowPort(gpWindow)), &rectSource, &rectDest, srcCopy, NULL);
  325.         time = TickCount () - time;
  326.         time = 200 * 60 / time;
  327.  
  328.         NumToString (rectSource.right - rectSource.left, str);
  329.         MoveTo (10, 20);
  330.         DrawString (str);
  331.         MoveTo (43, 20);
  332.         DrawString ("\px");
  333.         NumToString (rectSource.bottom - rectSource.top, str);
  334.         MoveTo (56, 20);
  335.         DrawString (str);
  336.         NumToString (time, str);
  337.         MoveTo (10, 35);
  338.         DrawString (str);
  339.         MoveTo (48, 35);
  340.         DrawString ("\pfps");
  341.         MoveTo (10, 50);
  342.         switch (gwLocOffscreen)
  343.         {
  344.             case kInVRAM:
  345.                 DrawString ("\pIn VRAM");
  346.                 break;
  347.             case kInAGP:
  348.                 DrawString ("\pIn AGP memory");
  349.                 break;
  350.             case kInSystem:
  351.                 DrawString ("\pIn system memory");
  352.                 break;
  353.             default:
  354.                 break;
  355.         }
  356.         UnlockPixels (GetGWorldPixMap (gpGWOffScreen));
  357.     }
  358.     else
  359.     {
  360.         SysBeep (30);
  361.         MoveTo (10, 20);
  362.         DrawString ("\pBlit test failed.");
  363.     }
  364.     SetPort (pCGrafSave);
  365. }
  366.  
  367. // --------------------------------------------------------------------------
  368.  
  369. // forces offscreen allocation (if different than current) in memory type specified and sets menu flag
  370.  
  371. void AllocBuffer (short location)
  372. {
  373.     MenuHandle hMenu;
  374.     short i;
  375.     
  376.     // check to see if we are allocated in the desired buffer
  377.     if (location != gwLocOffscreen) 
  378.     { 
  379.         // dispose to force a rebuild
  380.         if (gpGWOffScreen)
  381.             DisposeGWorld (gpGWOffScreen);
  382.         gpGWOffScreen = NULL;
  383.         gwLocOffscreen = location;
  384.     }
  385.     // ensure we are properly built
  386.     if (BuildOffscreen (&gpGWOffScreen, gpWindow, &gwLocOffscreen))
  387.     {
  388.         FillOffscreen (gpGWOffScreen);
  389.         BlitToWindow (gpGWOffScreen, gpWindow, &gwLocOffscreen);
  390.     }
  391.     
  392.     // set menus
  393.     hMenu = GetMenuHandle (kMenuFile);
  394.     for (i = kFileInVRAM; i <= kFileInSystem; i++)
  395.         CheckMenuItem (hMenu, i, false);
  396.     CheckMenuItem (hMenu, gwLocOffscreen, true);
  397. }
  398.  
  399. // --------------------------------------------------------------------------
  400.  
  401. void InitToolbox()
  402. {
  403.     MenuHandle menu;
  404.  
  405.     /*MaxApplZone ();
  406.  
  407.     InitGraf((Ptr) &qd.thePort);
  408.     InitFonts();
  409.     InitWindows();
  410.     InitMenus();
  411.     TEInit();
  412.     InitDialogs(nil);*/
  413.     InitCursor();
  414.     
  415.     //qd.randSeed =  TickCount();
  416.     SetQDGlobalsRandomSeed(TickCount());
  417.  
  418.     // Init Menus
  419.     menu = NewMenu (kMenuApple, "\p\024");            // new  apple menu
  420.     InsertMenu (menu, 0);                            // add menu to end
  421.     //AppendResMenu(menu, 'DRVR');
  422.     
  423.     menu = NewMenu (kMenuFile, "\pFile");            // new menu
  424.     InsertMenu (menu, 0);                            // add menu to end
  425.     AppendMenu (menu, "\pAllocate In VRAM;Allocate In AGP Memory;Allocate In System Memory;Run Blit Test;Quit/Q");         // add items
  426.     
  427.     DrawMenuBar();
  428.  
  429. // --------------------------------------------------------------------------
  430.  
  431. Boolean SetUp (void)
  432. {
  433.     Rect rectWindow;
  434.     MenuHandle hMenu;
  435.     long versionSystem;
  436.     short i;
  437.     
  438.     InitToolbox ();
  439.  
  440.     SetRect (&rectWindow, 0, 0, kWindowWidth, kWindowHeight);
  441.     OffsetRect (&rectWindow, kWindowOffset, kWindowOffset);
  442.     gpWindow = NewCWindow (NULL, &rectWindow, "\pNew NewGWorld Test", true, kWindowGrowDocumentProc, (WindowPtr) -1, false, 0);
  443.  
  444.     gNewNewGWorld = false;
  445.     // this will work 9.x
  446.     Gestalt (gestaltSystemVersion, &versionSystem);
  447.     if (0x00000900 <= (versionSystem & 0x00000FF00))
  448.         gNewNewGWorld = true;
  449.     else
  450.     {
  451.         // now it is tricky
  452.         // we will try to allocate in VRAM and find out where the allocation really ended up.
  453.         GWorldPtr pgwTest = NULL;
  454.         Rect rectTest = {0, 0, 10, 10};
  455.         //short wPixDepth = (**((CGrafPtr)gpWindow)->portPixMap).pixelSize; // window pixel depth
  456.         short wPixDepth = (**(GetPortPixMap(GetWindowPort(gpWindow)))).pixelSize;
  457.         GDHandle hgdWindow = GetWindowDevice (gpWindow);    // window GDevice
  458.         if ((noErr == NewGWorld (&pgwTest, wPixDepth, &rectTest, NULL, hgdWindow, noNewDevice | useDistantHdwrMem)) &&
  459.             (pgwTest) /*&& // if we had a good allocation
  460.             //(GetZone () != HandleZone ((Handle)((**pgwTest->portPixMap).baseAddr)))) // if we did not allocate in our zone
  461.             (GetZone () != HandleZone ((Handle)((**(GetPortPixMap(pgwTest))).baseAddr)))*/)
  462.             gNewNewGWorld = true;    
  463.         if (pgwTest)
  464.             DisposeGWorld (pgwTest);
  465.     }        
  466.     if (!gNewNewGWorld)
  467.     {
  468.         hMenu = GetMenuHandle (kMenuFile);
  469.         for (i = kFileInVRAM; i <= kFileInAGP; i++)
  470.              //DisableItem (hMenu, i);
  471.              DisableMenuItem(hMenu, i);
  472.         AllocBuffer (kInSystem);
  473.     }
  474.     else
  475.         AllocBuffer (kInVRAM);
  476.     return true;
  477. }
  478.  
  479. // --------------------------------------------------------------------------
  480.  
  481. void DoMenu (SInt32 menuResult)
  482. {
  483.     SInt16 theMenu;
  484.     SInt16 theItem;
  485.     //Str255 daName;
  486.     MenuRef theMenuHandle;
  487.         
  488.     theMenu = HiWord(menuResult);
  489.     theItem = LoWord(menuResult);
  490.     theMenuHandle = GetMenuHandle(theMenu);
  491.  
  492.     switch (theMenu)
  493.     {
  494.         case kMenuApple:
  495.             switch (theItem)
  496.             {
  497.                 case kAppleAbout:
  498.                     break;
  499.                 default:
  500.                     //OpenDeskAcc(daName);
  501.                     break;
  502.             }
  503.             break;
  504.         case kMenuFile:
  505.             switch (theItem)
  506.             {
  507.                 case kFileInVRAM:
  508.                     AllocBuffer (kInVRAM);
  509.                     break;
  510.                 case kFileInAGP:
  511.                     AllocBuffer (kInAGP);
  512.                     break;
  513.                 case kFileInSystem:
  514.                     AllocBuffer (kInSystem);
  515.                     break;
  516.                 case kFileTest:
  517.                     RunTest ();
  518.                     break;
  519.                 case kFileQuit:
  520.                     gDone = true;
  521.                     break;
  522.             }
  523.             break;
  524.     }
  525.     HiliteMenu(0);
  526.     DrawMenuBar();
  527. }
  528.  
  529. // --------------------------------------------------------------------------
  530.  
  531. void DoKey (SInt8 theKey, SInt8 theCode)
  532. {
  533.     #pragma unused (theKey, theCode)
  534. }
  535.  
  536. // --------------------------------------------------------------------------
  537.  
  538. void DoUpdate (WindowPtr pWindow)
  539. {
  540.     BlitToWindow (gpGWOffScreen, pWindow, &gwLocOffscreen);
  541. }
  542.  
  543. // --------------------------------------------------------------------------
  544.  
  545. void DoEvent (void)
  546. {
  547.     EventRecord theEvent;
  548.     Rect rectGrow;
  549.     WindowRef whichWindow;
  550.     long grow;
  551.     SInt32 menuResult;
  552.     SInt16 whatPart;
  553.     SInt8 theKey;
  554.     SInt8 theCode;
  555.     RgnHandle rgnHandle = NewRgn();
  556.     Rect    tempRect1;
  557.     
  558.     if (WaitNextEvent(everyEvent, &theEvent, gSleepTime, NULL))
  559.     {
  560.         switch (theEvent.what)
  561.         {
  562.             case mouseDown:
  563.                 whatPart = FindWindow(theEvent.where, &whichWindow);
  564.                 switch (whatPart)
  565.                 {
  566.                     case inGoAway:
  567.                         break;
  568.                     case inMenuBar:
  569.                         DrawMenuBar();
  570.                         menuResult = MenuSelect(theEvent.where);
  571.                         if (HiWord(menuResult) != 0)
  572.                             DoMenu(menuResult);
  573.                         break;
  574.                     case inDrag:
  575.                         //DragWindow (whichWindow, theEvent.where, &(**LMGetGrayRgn()).rgnBBox);
  576.                         GetRegionBounds(GetGrayRgn(), &tempRect1);
  577.                         DragWindow (whichWindow, theEvent.where, &tempRect1);
  578.                         // ensure we are properly built
  579.                         if (BuildOffscreen (&gpGWOffScreen, gpWindow, &gwLocOffscreen))
  580.                         {
  581.                             FillOffscreen (gpGWOffScreen);
  582.                             BlitToWindow (gpGWOffScreen, gpWindow, &gwLocOffscreen);
  583.                         }
  584.                         break;
  585.                     case inGrow:
  586.                         SetRect (&rectGrow, 100, 100, 20000, 20000);
  587.                         grow = GrowWindow (whichWindow, theEvent.where, &rectGrow);
  588.                         if (grow)
  589.                         {
  590.                             SizeWindow (whichWindow, grow & 0x0000FFFF, grow >> 16, true);
  591.                             // ensure offscreen buffer is reallocated
  592.                             if (gpGWOffScreen)
  593.                                 DisposeGWorld (gpGWOffScreen);
  594.                             gpGWOffScreen = NULL;
  595.                             AllocBuffer (gwLocOffscreen);
  596.                             //SetPort (whichWindow);
  597.                             SetPortWindowPort(whichWindow);
  598.                             //InvalRect (&whichWindow->portRect);                // redraw all
  599.                             InvalWindowRect (whichWindow, &tempRect1);
  600.                         }
  601.                         break;
  602.                     case inSysWindow:
  603.                         //SystemClick(&theEvent, whichWindow);
  604.                         break;
  605.                 }
  606.                 break;
  607.             case keyDown:
  608.             case autoKey:
  609.                 theKey = theEvent.message & charCodeMask;
  610.                 theCode = (theEvent.message & keyCodeMask) >> 8;
  611.                 if ((theEvent.modifiers & cmdKey) != 0)
  612.                 {
  613.                     menuResult = MenuKey(theKey);
  614.                     if (HiWord(menuResult) != 0)
  615.                         DoMenu (menuResult);
  616.                 }
  617.                 else
  618.                     DoKey (theKey, theCode);
  619.                 break;
  620.             case updateEvt:
  621.                 BeginUpdate((WindowPtr) theEvent.message);
  622.                 DoUpdate((WindowPtr) theEvent.message);
  623.                 EndUpdate((WindowPtr) theEvent.message);
  624.                 break;
  625.             case diskEvt:
  626.                 break;
  627.             case osEvt:
  628.                 break;
  629.  
  630.             case kHighLevelEvent:
  631.                 AEProcessAppleEvent(&theEvent);
  632.                 break;
  633.             
  634.         }
  635.     }
  636.     else
  637.     {
  638.         // idle tasks
  639.     }
  640.     
  641.     DisposeRgn(rgnHandle);
  642. }
  643.  
  644. // --------------------------------------------------------------------------
  645.  
  646. void CleanUp (void)
  647. {
  648.     MenuHandle hMenu;
  649.  
  650.     HideWindow (gpWindow);
  651.     if (gpWindow)
  652.         DisposeWindow (gpWindow);
  653.     gpWindow = NULL;
  654.     
  655.     // this is VERY important since the GWorld may not be in the application heap zone
  656.     // leaked memory here outside the app heap may not be recoverable without a restart
  657.     if (gpGWOffScreen)
  658.         DisposeGWorld (gpGWOffScreen);
  659.     gpGWOffScreen = NULL;
  660.     
  661.     hMenu = GetMenuHandle (kMenuFile);
  662.     DeleteMenu (kMenuFile);
  663.     DisposeMenu (hMenu);
  664.  
  665.     hMenu = GetMenuHandle (kMenuApple);
  666.     DeleteMenu (kMenuApple);
  667.     DisposeMenu (hMenu);
  668. }
  669.  
  670. // --------------------------------------------------------------------------
  671.  
  672. int main (void)
  673. {
  674.     if (SetUp ())
  675.         while (!gDone)
  676.             DoEvent ();
  677.     CleanUp ();
  678.     return 0;
  679. }
  680.  
  681.  
  682.